/*
 * Obstaculo.cpp
 *
 *  Created on: 01/09/2012
 *      Author: rodrigo
 */

#include "Obstaculo.h"
#include <math.h>

#define min(a, b)  (((a) < (b)) ? (a) : (b)) 
#define max(a, b)  (((a) > (b)) ? (a) : (b))

Obstaculo::Obstaculo(int x, int y, string rutaImagen, int ancho, int alto,
		int maximoX, int maximoY, int angulo) :
		ObjetoEstatico(x, y, maximoX, maximoY) {

	Punto pos(x, y);
	posicion = pos;
	setAngulo(angulo);

	int idImagen = GestionId::getId(rutaImagen, ancho, alto, 1, NO_ESPEJADA, angulo);
	addAnimacion(idImagen, 1000, 1);

	int destino_width = ancho;
	int destino_height = alto;

	if (angulo != 0) {
		CalcularVertices(ancho, alto, angulo, x, y);
		setAlto((max(vertices.posInfDer.getY(), vertices.posInfIzq.getY()))	- (min(vertices.posSupDer.getY(), vertices.posSupIzq.getY())));
		setAncho((max(vertices.posSupDer.getX(), vertices.posSupDer.getX())) - (min(vertices.posInfIzq.getX(), vertices.posSupIzq.getX())));
	} else {
		setAlto(destino_height);
		setAncho(destino_width);
	}

	string msg = "Añadido obstaculo en posicion (";
	msg = msg + Logger::intToString(x) + ";" + Logger::intToString(y) + ").";
	LOGUEAR(msg, 1);
}

void Obstaculo::CalcularVertices(int ancho, int alto, int angulo, int pos_x, int pos_y) {

	float radianes = 2 * 3.1416 * (360 - angulo) / 360;
	float coseno = (float) cos(radianes);
	float seno = (float) sin(radianes);

	float point1x = -alto * seno;
	float point1y = alto * coseno;
	float point2x = ancho * coseno - alto * seno;
	float point2y = alto * coseno + ancho * seno;
	float point3x = ancho * coseno;
	float point3y = ancho * seno;

	float minx = min (0, min(point1x, min(point2x, point3x)));
	float miny = min (0, min(point1y,min(point2y, point3y)));
	float maxx = max (point1x, max(point2x, point3x));
	float maxy = max (point1y, max(point2y, point3y));

	int destino_width = (int) ceil(fabs(maxx) - minx);
	int destino_height = (int) ceil(fabs(maxy) - miny);

	int x, y;
	int newx, newy;

	x = -ancho / 2;
	y = alto / 2;
	newx = destino_width / 2 + (x * coseno + y * seno);
	newy = destino_height / 2 - (y * coseno - x * seno);
	Punto vertice1(newx + pos_x, newy + pos_y);

	x = ancho / 2;
	y = -alto / 2;
	newx = destino_width / 2 + (x * coseno + y * seno);
	newy = destino_height / 2 - (y * coseno - x * seno);
	Punto vertice2(newx + pos_x, newy + pos_y);

	x = -ancho / 2;
	y = -alto / 2;
	newx = destino_width / 2 + (x * coseno + y * seno);
	newy = destino_height / 2 - (y * coseno - x * seno);
	Punto vertice3(newx + pos_x, newy + pos_y);

	x = ancho / 2;
	y = alto / 2;
	newx = destino_width / 2 + (x * coseno + y * seno);
	newy = destino_height / 2 - (y * coseno - x * seno);
	Punto vertice4(newx + pos_x, newy + pos_y);

	Punto rotados[4] = { vertice1, vertice2, vertice3, vertice4 };

	int minX =
			min (rotados[0].getX(), min(rotados[1].getX(), min(rotados[2].getX(), rotados[3].getX())));
	int maxX =
			max (rotados[0].getX(), max(rotados[1].getX(), max(rotados[2].getX(), rotados[3].getX())));

	int i, j;
	for (i = 0; i < 4; i++) {

		if (rotados[i].getX() == minX) {

			rotados[i].setX(maxX + 1);
			int preMinX =
					min (rotados[0].getX(), min(rotados[1].getX(), min(rotados[2].getX(), rotados[3].getX())));
			rotados[i].setX(minX);

			for (j = 0; j < 4; j++) {

				if (j == i)
					continue;
				if (rotados[j].getX() == preMinX) {

					if (rotados[i].getY() > rotados[j].getY()) {
						vertices.posSupIzq = rotados[j];
						vertices.posInfIzq = rotados[i];
					} else {
						vertices.posSupIzq = rotados[i];
						vertices.posInfIzq = rotados[j];
					}

					break;
				}
			}
			break;

		}

	}

	for (unsigned int k = 0; k < 4; k++) {

		if (k == i || k == j)
			continue;

		for (unsigned int n = 0; n < 4; n++) {

			if (n == k || n == i || n == j)
				continue;
			if (rotados[k].getY() > rotados[n].getY()) {
				vertices.posSupDer = rotados[n];
				vertices.posInfDer = rotados[k];
			} else {
				vertices.posSupDer = rotados[k];
				vertices.posInfDer = rotados[n];
			}

			break;
		}

		break;
	}
}

Obstaculo::~Obstaculo() {

}

bool Obstaculo::isDentro(Punto point, int pAlto, int pAncho) {

	/*if(point+(pAlto/2)< posicion+(alto/2) ||point+(pAlto/2)< posicion-(alto/2)){
	 if(point+(pAncho/2)<posicion+(ancho/2)||point+(pAncho/2)>posicion-(ancho/2)){
	 return true;
	 }}else if(point-(pAlto/2)< posicion+(alto/2) ||point-(pAlto/2)< posicion-(alto/2)){
	 if(point-(pAncho/2)<posicion+(ancho/2)||point-(pAncho/2)>posicion-(ancho/2)){
	 return true;
	 }
	 }*/

	return false;

}

idImagen_t Obstaculo::getIdImagen() {

	return v_animaciones.at(0)->getIdImagen();
}

int Obstaculo::getAngulo() {
	return this->angulo;
}
/*pair<idImagen_t, int> Obstaculo::getDibujable(Uint32 time) {

 return ObjetoEstatico::getDibujable(time);
 }*/
bool Obstaculo::ColisionOblicua(ObjetoEstatico* personaje) {
	return true;
}

void Obstaculo::setAngulo(int ang) {
	this->angulo = ang;
}

